/**
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

{% set cases = [
    {
        'description_test': '0. Simple class with default constructor, without fields and without methods',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '', 
        'checks': [],
        'decl_bodys': { 
            'SimpleClass': 'class SimpleClass {}' 
        }        
    },{
        'description_test': '1. Simple class with empty constructor, without fields and without methods',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '', 
        'checks': [],
        'decl_bodys': { 
            'SimpleClass': 'class SimpleClass { constructor(){}}' 
        }        
    },{
        'description_test': '2. Implement interface. Return type - simple class',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne {}', 
            'SimpleClass': 'class SimpleClass implements InterfaceOne {}'
        },
    },{
        'description_test': '3. Implement interface. Return type - interface',
        'class_name': 'SimpleClass',
        'return_type': 'InterfaceOne',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne {}', 
            'SimpleClass': 'class SimpleClass implements InterfaceOne {}'
        },
    },{
        'description_test': '4. Implements many interfaces. Return type - simple class',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne {}',
            'InterfaceTwo': 'interface InterfaceTwo {}',
            'InterfaceThree': 'interface InterfaceThree {}',
            'SimpleClass': 'class SimpleClass implements InterfaceOne, InterfaceTwo, InterfaceThree {}'
        },
    },{
        'description_test': '5. Implements many interfaces. Return type - interface',
        'class_name': 'SimpleClass',
        'return_type': 'InterfaceTwo',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne {}',
            'InterfaceTwo': 'interface InterfaceTwo {}',
            'InterfaceThree': 'interface InterfaceThree {}',
            'SimpleClass': 'class SimpleClass implements InterfaceOne, InterfaceTwo, InterfaceThree {}'
        },
    },{
        'description_test': '6. Inheritance class. Return type - children class',
        'class_name': 'ChildrenClass',
        'return_type': 'ChildrenClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'ParentClass': 'class ParentClass {}',
            'ChildrenClass': 'class ChildrenClass extends ParentClass {}' 
        },
    },{
        'description_test': '7. Inheritance class. Return type - parent class',
        'class_name': 'ChildrenClass',
        'return_type': 'ParentClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'ParentClass': 'class ParentClass {}',
            'ChildrenClass': 'class ChildrenClass extends ParentClass {}' 
        },
    },{
        'description_test': '8. Inheritance class. Return type - parent class 2 depth level',
        'class_name': 'ChildrenClass',
        'return_type': 'ParentParentClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'ParentParentClass': 'class ParentParentClass {}',
            'ParentClass': 'class ParentClass extends ParentParentClass{}',
            'ChildrenClass': 'class ChildrenClass extends ParentClass {}' 
        },
    },{
        'description_test': '9. Inheritance class and interface. Return type - interface (imlement parent class)',
        'class_name': 'ChildrenClass',
        'return_type': 'InterfaceOne',
        'construct_args': '',
        'checks': [],
        'decl_bodys': {
            'InterfaceOne': "interface InterfaceOne {}", 
            'ParentClass': 'class ParentClass implements InterfaceOne {}',
            'ChildrenClass': 'class ChildrenClass extends ParentClass {}' 
        },
    },{
        'description_test': '10. Inheritance class and interface. Return type - interface (imlements children class)',
        'class_name': 'ChildrenClass',
        'return_type': 'InterfaceOne',
        'construct_args': '',
        'checks': [],
        'decl_bodys': {
            'InterfaceOne': "interface InterfaceOne {}", 
            'ParentClass': 'class ParentClass {}',
            'ChildrenClass': 'class ChildrenClass extends ParentClass implements InterfaceOne {}' 
        },
    },{
        'description_test': '11. Implements interface - many depth level. Return type - interface 2 depth level',
        'class_name': 'SimpleClass',
        'return_type': 'InterfaceTwo',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne {}',
            'InterfaceTwo': 'interface InterfaceTwo extends InterfaceOne {}',
            'InterfaceThree': 'interface InterfaceThree extends InterfaceTwo {}',
            'SimpleClass': 'class SimpleClass implements InterfaceThree {}'
        },
    },{
        'description_test': '12. Implements interface - many depth level. Return type - interface 3 depth level',
        'class_name': 'SimpleClass',
        'return_type': 'InterfaceOne',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne {}',
            'InterfaceTwo': 'interface InterfaceTwo extends InterfaceOne {}',
            'InterfaceThree': 'interface InterfaceThree extends InterfaceTwo {}',
            'SimpleClass': 'class SimpleClass implements InterfaceThree {}'
        },
    },{
        'description_test': '13. Simple abstract class. Return type - AbstractSimpleClass',
        'class_name': 'SimpleClass',
        'return_type': 'AbstractSimpleClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'AbstractSimpleClass': 'abstract class AbstractSimpleClass {}',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleClass {}'
        },
    },{
        'description_test': '14. Simple abstract class. Return type - SimpleClass',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'AbstractSimpleClass': 'abstract class AbstractSimpleClass {}',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleClass {}'
        },
    },{
        'description_test': '15. Simple abstract class and interface (imlements simple class). Return type - SimpleClass',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': {
            'InterfaceOne': 'interface InterfaceOne {}', 
            'AbstractSimpleClass': 'abstract class AbstractSimpleClass {}',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleClass implements InterfaceOne {}'
        },
    },{
        'description_test': '16. Simple abstract class and interface (imlements simple class). Return type - AbstractSimpleClass',
        'class_name': 'SimpleClass',
        'return_type': 'AbstractSimpleClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': {
            'InterfaceOne': 'interface InterfaceOne {}', 
            'AbstractSimpleClass': 'abstract class AbstractSimpleClass {}',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleClass implements InterfaceOne {}'
        },
    },{
        'description_test': '17. Simple abstract class and interface (imlements simple class). Return type - Interface',
        'class_name': 'SimpleClass',
        'return_type': 'InterfaceOne',
        'construct_args': '',
        'checks': [],
        'decl_bodys': {
            'InterfaceOne': 'interface InterfaceOne {}', 
            'AbstractSimpleClass': 'abstract class AbstractSimpleClass {}',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleClass implements InterfaceOne {}'
        },
    },{
        'description_test': '18. Simple abstract class and interface (imlements abstract class). Return type - SimpleClass',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': {
            'InterfaceOne': 'interface InterfaceOne {}', 
            'AbstractSimpleClass': 'abstract class AbstractSimpleClass implements InterfaceOne {} ',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleClass {}'
        },
    },{
        'description_test': '19. Simple abstract class and interface (imlements abstract class). Return type - AbstractSimpleClass',
        'class_name': 'SimpleClass',
        'return_type': 'AbstractSimpleClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': {
            'InterfaceOne': 'interface InterfaceOne {}', 
            'AbstractSimpleClass': 'abstract class AbstractSimpleClass implements InterfaceOne {}',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleClass {}'
        },
    },{
        'description_test': '20. Simple abstract class and interface (imlements abstract class). Return type - Interface',
        'class_name': 'SimpleClass',
        'return_type': 'InterfaceOne',
        'construct_args': '',
        'checks': [],
        'decl_bodys': {
            'InterfaceOne': 'interface InterfaceOne {}', 
            'AbstractSimpleClass': 'abstract class AbstractSimpleClass implements InterfaceOne {}',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleClass {}'
        },
    },{
        'description_test': '21. Abstarct class and interface - many depth level. Return type - interface 2 depth level',
        'class_name': 'SimpleClass',
        'return_type': 'InterfaceOne',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'AbstractSimpleOneClass': 'abstract class AbstractSimpleOneClass{}',
            'InterfaceOne': 'interface InterfaceOne {}',
            'InterfaceTwo': 'interface InterfaceTwo extends InterfaceOne {}',
            'AbstractSimpleTwoClass': 'abstract class AbstractSimpleTwoClass extends AbstractSimpleOneClass implements InterfaceTwo {}',
            'AbstractSimpleThreeClass': 'abstract class AbstractSimpleThreeClass extends AbstractSimpleTwoClass {}',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleThreeClass{}'
        },
    },{
        'description_test': '22. Abstarct class and interface - many depth level. Return type - SimpleClass',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'AbstractSimpleOneClass': 'abstract class AbstractSimpleOneClass{}',
            'InterfaceOne': 'interface InterfaceOne {}',
            'InterfaceTwo': 'interface InterfaceTwo extends InterfaceOne {}',
            'AbstractSimpleTwoClass': 'abstract class AbstractSimpleTwoClass extends AbstractSimpleOneClass implements InterfaceTwo {}',
            'AbstractSimpleThreeClass': 'abstract class AbstractSimpleThreeClass extends AbstractSimpleTwoClass {}',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleThreeClass{}'
        },
    },{
        'description_test': '23. Abstarct class and interface - many depth level. Return type - abstaract 3 depth level',
        'class_name': 'SimpleClass',
        'return_type': 'AbstractSimpleOneClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'AbstractSimpleOneClass': 'abstract class AbstractSimpleOneClass {}',
            'InterfaceOne': 'interface InterfaceOne {}',
            'InterfaceTwo': 'interface InterfaceTwo extends InterfaceOne {}',
            'AbstractSimpleTwoClass': 'abstract class AbstractSimpleTwoClass extends AbstractSimpleOneClass implements InterfaceTwo {}',
            'AbstractSimpleThreeClass': 'abstract class AbstractSimpleThreeClass extends AbstractSimpleTwoClass {}',
            'SimpleClass': 'class SimpleClass extends AbstractSimpleThreeClass {}'
        },
    },{
        'description_test': '24. Multilevel inheritance classes. Return type - children class',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'SimpleOneClass': 'class SimpleOneClass {}',
            'SimpleTwoClass': 'class SimpleTwoClass extends SimpleOneClass {}',
            'SimpleThreeClass': 'class SimpleThreeClass extends SimpleTwoClass {}',
            'SimpleClass': 'class SimpleClass extends SimpleThreeClass {}'
        },
    },{
        'description_test': '25. Multilevel inheritance classes. Return type - class 2 depth level',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleTwoClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'SimpleOneClass': 'class SimpleOneClass {}',
            'SimpleTwoClass': 'class SimpleTwoClass extends SimpleOneClass {}',
            'SimpleThreeClass': 'class SimpleThreeClass extends SimpleTwoClass {}',
            'SimpleClass': 'class SimpleClass extends SimpleThreeClass {}'
        },
    },{
        'description_test': '26. Multilevel inheritance classes. Return type - class 3 depth level',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleOneClass',
        'construct_args': '',
        'checks': [],
        'decl_bodys': { 
            'SimpleOneClass': 'class SimpleOneClass {}',
            'SimpleTwoClass': 'class SimpleTwoClass extends SimpleOneClass {}',
            'SimpleThreeClass': 'class SimpleThreeClass extends SimpleTwoClass {}',
            'SimpleClass': 'class SimpleClass extends SimpleThreeClass {}'
        },
    },{
        'description_test': '27. Class with one field. Field initilization inside constructor block',
        'class_name': 'WithFieldClass',
        'return_type': 'WithFieldClass',
        'construct_args': '',
        'checks': [{
            'get_actual_result': 'awaited_result.value',
            'get_expected_result': '''"ok"'''
        }],
        'decl_bodys': { 
            'WithFieldClass': '''class WithFieldClass { 
                value: string
                constructor(){
                    this.value = "ok"
                }
            }'''
        },
    },{
        'description_test': '28. Class with one field. Field initilization in class block',
        'class_name': 'WithFieldClass',
        'return_type': 'WithFieldClass',
        'construct_args': '',
        'checks': [{
            'get_actual_result': 'awaited_result.value',
            'get_expected_result': '''"ok"'''
        }],
        'decl_bodys': { 
            'WithFieldClass': '''class WithFieldClass { 
                value = "ok"
            }'''
        },
    },{
        'description_test': '29. Class with many field. Fields initilization by constructor arguments',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': "\"val_1\", 1200, ['1', 135, \"frfrf\", c'W', true, 16.1f], true",
        'checks': [{
            'get_actual_result': 'awaited_result.valueStr',
            'get_expected_result': '''"val_1"'''
        },{
            'get_actual_result': 'awaited_result.valueArray.length',
            'get_expected_result': 6
        },{
            'get_actual_result': 'awaited_result.valueArray[0]',
            'get_expected_result': "'1'"
        },{
            'get_actual_result': 'awaited_result.valueArray[1]',
            'get_expected_result': 135
        },{
            'get_actual_result': 'awaited_result.valueArray[2]',
            'get_expected_result': "\"frfrf\""
        },{
            'get_actual_result': 'awaited_result.valueArray[3]',
            'get_expected_result': "c'W'"
        },{
            'get_actual_result': 'awaited_result.valueArray[4]',
            'get_expected_result': "true"
        },{
            'get_actual_result': 'awaited_result.valueArray[5]',
            'get_expected_result': "16.1f"
        },{
            'get_actual_result': 'awaited_result.valueInt',
            'get_expected_result': 1200
        },{
            'get_actual_result': 'awaited_result.valueBoolean',
            'get_expected_result': 'true'
        }
        ],
        'decl_bodys': { 
            'SimpleClass': '''class SimpleClass { 
                valueStr: string
                valueInt: int
                valueArray: Array<Any>
                valueBoolean: boolean
                constructor(
                    value: string,
                    valueInt: int,
                    valueArray: Array<Any>,
                    valueBool: boolean
                ){
                    this.valueArray = valueArray;
                    this.valueInt = valueInt
                    this.valueStr = value; this.valueBoolean = valueBool
                }

            }'''
        },
    },{
        'description_test': '30. Implement interface with one method. Return type - simple class',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '',
        'checks': [{
            'get_actual_result': 'awaited_result.getMethodValue()',
            'get_expected_result': '''"ok"'''
        }],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne { getMethodValue(): string }', 
            'SimpleClass': 'class SimpleClass implements InterfaceOne { getMethodValue(): string { return "ok"}}'
        },
    },{
        'description_test': '31. Implement interface with one method. Return type - interface',
        'class_name': 'SimpleClass',
        'return_type': 'InterfaceOne',
        'construct_args': '',
        'checks': [{
            'get_actual_result': 'awaited_result.getMethodValue()',
            'get_expected_result': '''"ok"'''
        }],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne { getMethodValue(): string }', 
            'SimpleClass': 'class SimpleClass implements InterfaceOne { getMethodValue(): string { return "ok"}}'
        },
    },{
        'description_test': '32. Abstract class with one abstract method. Return type - simple class',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '',
        'checks': [{
            'get_actual_result': 'awaited_result.getMethodValue()',
            'get_expected_result': '''"ok"'''
        }],
        'decl_bodys': { 
            'AbstractClassOne': 'abstract class AbstractClassOne { abstract getMethodValue(): string }', 
            'SimpleClass': 'class SimpleClass extends AbstractClassOne { getMethodValue(): string { return "ok"}}'
        },
    },{
        'description_test': '33. Abstract class with one abstract method. Return type - abstract class',
        'class_name': 'SimpleClass',
        'return_type': 'AbstractClassOne',
        'construct_args': '',
        'checks': [{
            'get_actual_result': 'awaited_result.getMethodValue()',
            'get_expected_result': '''"ok"'''
        }],
        'decl_bodys': { 
            'AbstractClassOne': 'abstract class AbstractClassOne { abstract getMethodValue(): string }', 
            'SimpleClass': 'class SimpleClass extends AbstractClassOne { getMethodValue(): string { return "ok"}}'
        },
    },{
        'description_test': '34. Implement interface with one method, abstract class that implements this interface, and class that implemented method. Return type - interface',
        'class_name': 'SimpleClass',
        'return_type': 'InterfaceOne',
        'construct_args': '',
        'checks': [{
            'get_actual_result': 'awaited_result.getMethodValue()',
            'get_expected_result': '''"ok"'''
        }],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne { getMethodValue(): string }', 
            'AbstractClassOne': 'abstract class AbstractClassOne implements InterfaceOne {}', 
            'SimpleClass': 'class SimpleClass extends AbstractClassOne { getMethodValue(): string { return "ok"}}'
        },
    },{
        'description_test': '35. Implement interface with one method, abstract class that implements this interface, and class that implemented method. Return type - abstract class',
        'class_name': 'SimpleClass',
        'return_type': 'AbstractClassOne',
        'construct_args': '',
        'checks': [{
            'get_actual_result': 'awaited_result.getMethodValue()',
            'get_expected_result': '''"ok"'''
        }],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne { getMethodValue(): string }', 
            'AbstractClassOne': 'abstract class AbstractClassOne implements InterfaceOne {}', 
            'SimpleClass': 'class SimpleClass extends AbstractClassOne { getMethodValue(): string { return "ok"}}'
        },
    },{
        'description_test': '36. Implement interface with one method, abstract class that implements this interface, and class that implemented method. Return type - class',
        'class_name': 'SimpleClass',
        'return_type': 'SimpleClass',
        'construct_args': '',
        'checks': [{
            'get_actual_result': 'awaited_result.getMethodValue()',
            'get_expected_result': '''"ok"'''
        }],
        'decl_bodys': { 
            'InterfaceOne': 'interface InterfaceOne { getMethodValue(): string }', 
            'AbstractClassOne': 'abstract class AbstractClassOne implements InterfaceOne {}', 
            'SimpleClass': 'class SimpleClass extends AbstractClassOne { getMethodValue(): string { return "ok"}}'
        },
    }


] %}

 {% from "16.concurrency/03.asynchronous_api/async_api_helper.jinja" import generate_async, call_async %}

 {% macro generate_complete_test(declaration_type='function') %}
 {% for c in cases %}

 /*---
 desc: The return type of an async {{declaration_type}} must be Promise<{{c.class_name}}>. {{c.description_test}}
 ---*/

{%- for key, value in c.decl_bodys.items() %}
{{ value|e }}
{%- endfor%}

{%- set params = {
    'name': 'noParams',
    'body': 'return new ' + c.class_name + '('+ c.construct_args + ')',
    'return_type': ': Promise<' + c.return_type + '>',
    'class_name': 'AsyncMethodReturnClass'
} %}

{{ generate_async(declaration_type, params) }}

async function startTest(){
    let result = {{ call_async(declaration_type, params) }}
    arktest.assertTrue(result instanceof Promise)
    let awaited_result = await result

    {% for key, value in c.decl_bodys.items()  %}
    arktest.assertTrue(awaited_result instanceof {{key|e}}, 'Result is not instanceof {{key|e}}')
    {%- endfor %}
    {%- for check in c.checks %}

    let actual_{{loop.index}} = {{check.get_actual_result}}
    let expected_{{loop.index}} = {{check.get_expected_result}}
    arktest.assertEQ(expected_{{loop.index}}, actual_{{loop.index}})
    {%- endfor %}
}

function main(){
    waitForCompletion(startTest)
}

 {% endfor %}
 {% endmacro %}